package com.translate.web.config.common.excecption;

import java.nio.file.AccessDeniedException;
import java.sql.SQLIntegrityConstraintViolationException;
import java.util.Objects;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.util.NestedServletException;

import com.fasterxml.jackson.databind.exc.InvalidFormatException;
import com.response.vo.ResponseModel;



/**
 * 自定义异常处理类 针对不同的异常自定义不同的方法 环绕通知 切面:针对所有的controller中抛出的异常
 * 若使用@ControllerAdvice,则不会自动转换为JSON格式
 */
@RestControllerAdvice
public class RestExceptionHandler {
	
	private static Logger log = LoggerFactory.getLogger(RestExceptionHandler.class);

	/**
	 * 业务异常处理
	 * 
	 * @param e
	 * @return ErrorInfo
	 */
	@ExceptionHandler({ NestedServletException.class })
	public ResponseEntity<ErrorInfo> businessExceptionHandler(HttpServletRequest request, NestedServletException e)
			throws BaseBusinessException {
		
		e.printStackTrace();
		log.debug("NestedServletException error: {}", e);
		
		return new ResponseEntity<ErrorInfo>(new ErrorInfo(0, e.getMessage()), HttpStatus.CONFLICT);
	}
	
	@ExceptionHandler({ BaseBusinessException.class })
	public ResponseEntity<ErrorInfo> businessExceptionHandler(HttpServletRequest request, BaseBusinessException e)
			throws BaseBusinessException {
		e.printStackTrace();
		return new ResponseEntity<ErrorInfo>(new ErrorInfo(e.getCode(), e.getMessage()), HttpStatus.CONFLICT);
	}

	/**
	 * 业务异常处理
	 * 
	 * @param e
	 * @return ErrorInfo
	 */
	@ExceptionHandler({ AccessDeniedException.class })
	public ResponseEntity<ErrorInfo> BusinessExceptionHandler(HttpServletRequest request, AccessDeniedException e)
			throws BaseBusinessException {
		e.printStackTrace();
		return new ResponseEntity<ErrorInfo>(new ErrorInfo(401, e.getMessage()), HttpStatus.UNAUTHORIZED);
	}

	@ExceptionHandler(value = MethodArgumentNotValidException.class)
	public ResponseModel<String> resolveException(MethodArgumentNotValidException ex) {
		BindingResult bindingResult = ex.getBindingResult();
		String errorField = "";
		String errorCode;
		if (bindingResult.hasFieldErrors()) {
			errorCode = Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage();
//			errorField = String.format("Field: %s", bindingResult.getFieldError().getField());
		} else {
			errorCode = Objects.requireNonNull(bindingResult.getGlobalError()).getDefaultMessage();
		}

//		return ResponseModel.errorMsg("", errorField.concat(":").concat(errorCode));
		return ResponseModel.errorMsg("", errorField.concat(errorCode));
	}
	/**
	 * 只要抛出该类型异常,则由此方法处理 并由此方法响应出异常状态码及消息 如:RoleController.getRoleById(String id)方法
	 * 
	 * @param request
	 * @param e
	 * @return
	 * @throws Exception
	 */
	@ExceptionHandler(value = Exception.class)
	public ResponseModel<String> handleException(HttpServletRequest request, Exception e) throws Exception {
		e.printStackTrace();
		return ResponseModel.errorMsg("", e.toString());
	}
	
	@ExceptionHandler(value = HttpMessageNotReadableException.class)
	public ResponseModel<String> httpException(HttpServletRequest request, HttpMessageNotReadableException e) throws Exception {
		e.printStackTrace();
		return ResponseModel.errorMsg("", "请传递参数或参数类型不正确");
	}
	
	

	
	@ExceptionHandler(value = Error.class)
	public ResponseModel<String> handleException(HttpServletRequest request, Error e) throws Exception {
		e.printStackTrace();
		return ResponseModel.errorMsg("", e.toString());
	}
	
	
	@ExceptionHandler(value = RuntimeException.class)
	public ResponseModel<String> handleException(HttpServletRequest request, RuntimeException e) throws Exception {
		e.printStackTrace();
		return ResponseModel.errorMsg("", "运行异常");
	}

	
	@ExceptionHandler(value = InvalidFormatException.class)
	public ResponseModel<String> invalidException(HttpServletRequest request, InvalidFormatException e) throws Exception {
		e.printStackTrace();
		return ResponseModel.errorMsg("", "参数错误");
	}
	
	
	
	@ExceptionHandler(value = LoginError.class)
	public ResponseModel<String> handleException(HttpServletRequest request, LoginError e) throws Exception {
		return ResponseModel.errorMsg("", e.getResponseCode());
	}

	@ExceptionHandler(value = SQLIntegrityConstraintViolationException.class)
	public ResponseModel<String> handleException(HttpServletRequest request, SQLIntegrityConstraintViolationException e)
			throws Exception {
		e.printStackTrace();
		return ResponseModel.errorMsg("", "违反主键约束，请勿重复添加: " + e.getMessage());
	}

	@ExceptionHandler(value = DuplicateKeyException.class)
	public ResponseModel<String> handleException(HttpServletRequest request, DuplicateKeyException e)
			throws Exception {
		e.printStackTrace();
		return ResponseModel.errorMsg("", "请勿重复添加" );
	}

}
